CSS Grid Layout (一)

前言

在介绍Grid之前,先来说一下flex吧,引用阮大神的一句话:2009年,W3C 提出了一种新的方案—-Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。在这几年,flex布局已然成为前端的主流布局框架,每一个前端开发者都必须要掌握flexbox的用法。
然而,在2017年,Grid来势汹汹,声势浩大,相信大家就算没有在项目中使用过,也一定听过这个。Grid最大的特色,就是采用了二维布局,之前的布局方式都是采用一维布局。目前Grid的规范也逐渐完善,flex和grid各有千秋,日后这个后起之秀会不会成为web布局的扛把子,谁也说不准。

下面,就来介绍下本文的主角 Grid

简介已经支持情况

Grid简介

Grid:CSS网格布局(又名“网格”)是一个二维的基于网格的布局系统,其目的只在于完全改变我们设计基于网格的用户界面的方式。CSS一直用来布局网页,但一直都不完美。 一开始我们使用table 做布局,然后转向浮动、定位以及inline-block,但所有这些方法本质上都是 Hack 的方式,并且遗漏了很多重要的功能(例如垂直居中)。 Flexbox的出现在一定程度上解决了这个问题,但是它的目的是为了更简单的一维布局,而不是复杂的二维布局(Flexbox和Grid实际上一起工作得很好)。 只要我们一直在制作网站,我们就一直在为解决布局问题不断探索, 而Grid是第一个专门为解决布局问题而生的CSS模块。

浏览器支持情况

浏览器支持情况ß

Gird的基本概念

1.网格容器(Grid Container),对应Flexbox布局中的Flex容器

元素应用display:grid,它是其所有网格项的父元素。下面例子container就是网格容器。

1
2
3
4
5
6
7
8
9
<div class="container">
<div class="item item-1"></div>
<div class="item item-2"></div>
<div class="item item-3"></div>
</div>

.container {
display: grid;
}

2.网格项(Grid Item), 对应Flexbox布局中的Flex项目

网格容器的子元素,下面的item元素是网格项,但sub-item不是。

1
2
3
4
5
6
7
<div class="container">
<div class="item"></div>
<div class="item">
<p class="sub-item"></p>
</div>
<div class="item"></div>
</div>

3.网格线(Grid lines)

网格线是用来在水平和垂直方向分割网格的线。水平方向的网格线是从左向右;垂直方向是从上往下。网格线的编号都是从1开始的。

网格线

4.网格轨道(Grid Track)

两个相邻的网格线之间为网格轨道。你可以认为它们是网格的列或行。

5.网格单元(Grid Cell)

两个相邻的列网格线和两个相邻的行网格线组成的是网格单元,它是最小的网格单元。

6.网格区(Grid Area)

网格区是由任意数量网格单元组成。

父容器(Grid Container)的属性

display

将元素定义为 grid contaienr,并为其内容建立新的网格格式化上下文(grid formatting context)。
属性值:

  • grid: 生成块级网格
  • inline-grid: 生成行内网格
  • subgrid: 如果网格容器本身是网格项grid item(嵌套网格容器),此属性用来继承其父网格容器的列、行大小。
1
2
3
.container {
display: grid | inline-grid | subgrid;
}

注意:column, float, clear, 以及 vertical-align 对一个 grid container 没有影响

grid-template-columns / grid-template-rows (网格列和网格行)

使用以空格分隔的多个值来定义网格的列和行。这些值表示轨道大小,它们之间的空格代表表格线。当你设置行或列大小为auto时,网格会自动分配空间和网格线名称
eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 基本用法
.container {
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}

// 可以给每条网格线命名
.container {
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}

 // 每条网格线也可以不止一个名字
.container {
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end row2-start] 100px [third-line] auto [last-line];
}

// 如果有重复的部分,可以使用repeat函数
.container {
grid-template-columns: repeat(3, 30px [col]) 40px;
}
等价于
.container {
30px [col] 30px [col] 30px [col] 40px;
}

可以使用fr单位可以将容器分为几等份,如果和实际值一起用,则代表分割剩余的部分,例如下面分成三等份

1
2
3
4
5
6
7
8
9
.container{
display:grid;
grid-template-columns: 1fr 1fr 1fr;
}

.container{
display:grid;
grid-template-columns: 1fr 100px 1fr 1fr;
}

网格项的属性

网格项属性

  • grid-column-start:设置网格项目垂直方向的开始位置网格线
  • grid-column-end:设置网格项目垂直方向的结束位置网格线
  • grid-row-start:设置网格项目水平方向的开始位置网格线
  • grid-row-end:设置网格项目水平方向的结束位置网格线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<section class="grid-1">  
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
<div class="item-4">4</div>
<div class="item-5">5</div>
<div class="item-6">6</div>
</section>

.grid-1 {
display: grid;
width: 100%;
max-width: 600px;
margin: 0 auto;
grid-template-columns: 300px 200px 100px;
grid-template-rows: 100px 50px;
}

.item-2 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 2;
}

// 两个属性缩写
item-2 {
grid-column: 2 / 4;
grid-row: 1 / 2;
}

// 四个属性缩写
grid-row-start / grid-column-start/ grid-row-end / grid-column-end
item-2 {
grid-area: 1 / 2 / 2 / 4;
}

'结果'

合并单元格

其实上面的例子中已经实现了两个单元格合并(第二列和第三列),其实在Grid布局中提供了一个span关键词来实现单元格的跨越,span 后面跟的数字表示跨越多少个单元格。类似于table中的合并单元格,比如colspan合并列,rowspan合并行。

注意:如果没有设置grid-column-end或grid-row-end,默认将跨越一个轨道。项目也可以重叠,设置z-index来确定堆叠顺序。

1
2
3
4
5
6
7
8
9
10
// 等价与上面的合并第二列和第三列
.item-2 {
grid-column: 2 / span 2;
grid-row: 1;
}

或者
.item-2 {
grid-area: 2 / 1 / span 2;
}

单个网格项垂直于列网格线的对齐方式

属性值:

  • start: 网格区域左对齐。
  • end: 网格区域右对齐。
  • center: 网格区域居中。
  • stretch: 网格区域填满。
1
2
3
.item-1{
justify-self: start | end | center | stretch;
}

也可以给父容器设置justify-items,达到全部网格项对齐

单个网格项垂直于列网格线的对齐方式

属性值:

  • start: 网格区域顶部对齐。
  • end: 网格区域底部对齐。
  • center: 网格区域居中。
  • stretch: 网格区域填满。
1
2
3
.item-1{
align-self: start | end | center | stretch;
}

也可以在容器上设置align-items,达到全部网格项对齐

未完待续…

感谢支持,我会不断进步